//
//  XLRecordTool.m
//  XiangLove
//
//  Created by 宋振 on 2018/8/8.
//  Copyright © 2018年 BAOMIHUA.COM. All rights reserved.
//

//@"xlRecorder.mp4"
#define kXLRecordFilePath       @"wav"



#import "XLRecordTool.h"
#import "lame.h"

@interface XLRecordTool ()<AVAudioRecorderDelegate>



/**  录音文件地址   **/
@property (nonatomic, strong) NSURL *  recordFileUrl;
@property (nonatomic, copy) NSString *  filePath;

/** 定时器 **/
@property (nonatomic, strong) NSTimer *  timer;



@end

@implementation XLRecordTool
{
    /** 时间读秒 **/
    NSInteger secondCount;
    
    //
    NSString *mp3FilePath;
}

/**
 设置单例
 */
static id instance;

#pragma mark    -   -   - 设计单例 -    -   -
+ (instancetype)shareRecordTool
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (!instance) {
            instance = [[self alloc] init];
        }
    });
    
    return instance;
}

+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (instance == nil) {
            instance = [super allocWithZone:zone];
        }
    });
    
    return instance;
}

#pragma mark        - - - 开始录音 - - -

/**
 开始录音
 */
- (void)startRecord
{
    //录音时停止播放
    [self stopPlayRecord];
    
    //删除曾经生成的文件
    [self destroyOldFileRecord];
    
    //开始进入录音状态
    [self.recorder record];
    
    //秒
    secondCount = 0;
    
    if (self.playCost > 0) {
        secondCount = self.playCost;
    }
    
    //计时
    self.timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(updateTimer) userInfo:nil repeats:YES];
    
    //加入线程
    [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
    
    [self.timer fire];
    
}

#pragma mark        - - - 播放录音文件 - - -

/**
 播放录音文件
 */
- (void)playRecord
{
    //停止录音
    [self.recorder stop];
    
    //是否正在播放
    if ([self.player isPlaying]) {
        
        [self.player stop];
        
        return;
    }
    
    NSError *error;

    if (self.playUrl) {
        
        NSString *playFileUrl;
        
        if (self.playUrl) {
            
            AVAudioSession *audioSession = [AVAudioSession sharedInstance];
            NSError *err = nil;
            [audioSession setCategory :AVAudioSessionCategoryPlayback error:&err];
            
            NSData * audioData = [NSData dataWithContentsOfURL:[NSURL URLWithString:K_DEFULT(self.playUrl)]];
            
            
            //将数据保存到本地指定位置
            NSString *docDirPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
            playFileUrl = [NSString stringWithFormat:@"%@/%@.mp3", docDirPath , @"temp"];
            [audioData writeToFile:playFileUrl atomically:YES];
            
//            NSURL *fileURL = [NSURL fileURLWithPath:filePath];
            self.player = [[AVAudioPlayer alloc] initWithData:audioData error:&error];
            
            
        }else{
            playFileUrl = self.filePath;
            
            self.playCost = 0;
            self.playUrl = nil;
            
            self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL URLWithString:playFileUrl] error:&error];
        }
        
        self.recordFileUrl = [NSURL URLWithString:playFileUrl];
        
//        self.recordFileUrl = [NSURL URLWithString:playFileUrl];
    }else if (!self.recordFileUrl)
    {
        NSLog(@"recordFileUrl(NSURL) 暂无参数信息");
    }
    
    [self.player play];
    
    
//    self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:self.recordFileUrl error:&error];
//
//
//    [self.player prepareToPlay];
//
//    [self.player play];
}


#pragma mark        - - - 停止播放 - - -

/**
 停止播放语音
 */
- (void)stopPlayingRecord
{
    [self.player stop];
}

#pragma mark        - - - 停止录音 - - -

/**
 停止录音
 */
- (void)stopRecord
{
    [self.recorder stop];
    [self.timer invalidate];
    
    if (self.filePath.length > 0) {
        
        //转换mp3
        [self converToMp3];
        
    }
    
    //恢复回放标志
    AVAudioSession *session = [AVAudioSession sharedInstance];
    
    //此处需要恢复设置回放标志，否则会导致其它播放声音也会变小
    
    NSError *seesionError;
    
    [session setCategory:AVAudioSessionCategoryPlayAndRecord error:&seesionError];
    
    
    
    UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
    AudioSessionSetProperty (
                             kAudioSessionProperty_OverrideAudioRoute,
                             sizeof (audioRouteOverride),
                             &audioRouteOverride
                             );
#pragma clang diagnostic pop
    if(!session) {
        DebugLog(@"Error creating session: %@", [seesionError description]);
    }
    else {
        [session setActive:YES error:nil];
    }
    
    
}

#pragma mark        - - - 转换MP3 - - -
- (void) converToMp3
{
    if (self.filePath.length <= 0) {
        return;
    }
    
    NSString *cafFilePath =self.filePath;
    
    NSString *mp3FileName = @"Mp3File";
    mp3FileName = [mp3FileName stringByAppendingString:@".mp3"];
    
    mp3FilePath = mp3FileName;
    
    NSString *mp3FilePaths = [NSTemporaryDirectory() stringByAppendingPathComponent:mp3FileName];
    
    NSFileManager *fm = [NSFileManager defaultManager];
    
    if (![fm fileExistsAtPath:cafFilePath]){
        
        NSLog(@"file path error!");
        
        return;
        
    }
    
//    self.filePath = mp3FilePath;
    
    @try {
        int read, write;
        
        FILE *pcm = fopen([cafFilePath cStringUsingEncoding:1], "rb");  //source
        fseek(pcm, 4*1024.0, SEEK_CUR);                                   //skip file header
        FILE *mp3 = fopen([mp3FilePaths cStringUsingEncoding:1], "wb");  //output
        
        const int PCM_SIZE = 8192;
        const int MP3_SIZE = 8192;
        short int pcm_buffer[PCM_SIZE*2];
        unsigned char mp3_buffer[MP3_SIZE];
        
        lame_t lame = lame_init();
        lame_set_in_samplerate(lame, 11025);
        lame_set_VBR(lame, vbr_default);
        lame_init_params(lame);
        lame_set_brate(lame,8);
        lame_set_mode(lame,3);
        lame_set_quality(lame,5); /* 2=high 5 = medium 7=low 音质*/
        lame_init_params(lame);
        

        
        do {
            
            read = (int)fread(pcm_buffer, 2*sizeof(short int), PCM_SIZE, pcm);
            if (read == 0)
                write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
            else
                write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE);
            
            fwrite(mp3_buffer, write, 1, mp3);
            
        } while (read != 0);
        
        lame_close(lame);
        fclose(mp3);
        fclose(pcm);
    }
    @catch (NSException *exception) {
        NSLog(@"%@",[exception description]);
    }
    @finally {
        [[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategorySoloAmbient error: nil];
    }
}

#pragma mark        - - - 销毁录音 - - -

/**
 销毁录音
 */
- (void)destroyRecord
{
    [self destroyOldFileRecord];
}

#pragma mark        - - - 更新时间方法 - - -

/**
 时间更新 可操作界面显示
 */
- (void)updateTimer
{
    [self.recorder updateMeters];
    
    //音量
    double lowPassResults = pow(10, (0.05 * [self.recorder peakPowerForChannel:0]));
    float result  = 10 * (float)lowPassResults;
    NSLog(@"%f", result);
    
    int voice = 0;
    if (result > 0 && result <= 1.3) {
        voice = 1;
    } else if (result > 1.3 && result <= 2) {
        voice = 2;
    } else if (result > 2 && result <= 3.0) {
        voice = 3;
    } else if (result > 3.0 && result <= 3.0) {
        voice = 4;
    } else if (result > 5.0 && result <= 10) {
        voice = 5;
    } else if (result > 10 && result <= 40) {
        voice = 6;
    } else if (result > 40) {
        voice = 7;
    }
    
    secondCount++;
    
    //更新时间
    if (self.delegate && [_delegate respondsToSelector:@selector(updateTime:)]) {
        [self.delegate updateTime:secondCount];
    }
}

#pragma mark        - - - 获取录音时长 - - -

- (NSInteger)getRecorderTime
{
    return secondCount;
}


#pragma mark        - - - 获取前面录入的文件信息 - - -

//获取录音信息
- (NSData *)getRecorderData
{
    if (self.filePath.length > 0) {
        
        NSData *recorderData = [NSData dataWithContentsOfFile:self.filePath];
        
        return recorderData;
    }
    
    return nil;
}

//获取录音
- (NSString *)getRecorderUrl
{
    if (self.filePath.length > 0) {
        
        return [NSTemporaryDirectory() stringByAppendingPathComponent:mp3FilePath];;
        return self.filePath;
        
    }
    
    return nil;
}



#pragma mark        - - - 停止播放公共方法 - - -

/**
 停止播放
 */
- (void)stopPlayRecord
{
    self.playCost = 0;
    self.playUrl = nil;
    
    [self.recorder stop];
    [self.timer invalidate];
    
    [self.player stop];
}

#pragma mark        - - - 销毁以往的录音文件 - - -

/**
 销毁录音
 */
- (void)destroyOldFileRecord
{
    secondCount = 0;
    
    NSFileManager *fileManager = [NSFileManager defaultManager];
    
    if (self.recordFileUrl) {
        [fileManager removeItemAtURL:self.recordFileUrl error:NULL];
    }
}

#pragma mark        - - - 生成录音对象 - - -

- (AVAudioRecorder *)recorder
{
    if (!_recorder) {
        
        //设置类型
        AVAudioSession *session = [AVAudioSession sharedInstance];
        
        NSError *error;
        
        [session setCategory:AVAudioSessionCategoryPlayAndRecord error:&error];
        
        //创建成功
        if (session) {
            [session setActive:YES error:nil];
        }else{
            NSLog(@"session == nil, so the create is failt");
        }
        
        
        //1.获取沙盒
        NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
        
        //2.获取路径
        NSString *filePaths = [path stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@",[NSString uuid],kXLRecordFilePath]];
        
        //3.生成
        self.recordFileUrl = [NSURL URLWithString:filePaths];
        self.filePath = filePaths;
        
        //4.设置录音参数
        NSMutableDictionary *setDic = [NSMutableDictionary dictionaryWithCapacity:1];
        
        //4.1音频格式 (LinearPCM无损，但是体积较为庞大)
        [setDic setObject:[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];
        
        //4.2采样率    AVSampleRateKey==8000/44100/96000（影响音频的质量）
        [setDic setObject:[NSNumber numberWithFloat:11025.0] forKey:AVSampleRateKey];
        
        //4.3音频通道 1 或 2
        [setDic setObject:[NSNumber numberWithInt:2] forKey:AVNumberOfChannelsKey];
        
        //4.4线性采样位数  8、16、24、32
        [setDic setObject:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
        
        //4.5录音质量
        [setDic setObject:[NSNumber numberWithInt:(int32_t)AVAudioQualityMedium] forKey:AVEncoderAudioQualityKey];
        
        //创建录音机对象
        
        NSError *recordError = nil;
        
        self.recorder = [[AVAudioRecorder alloc] initWithURL:self.recordFileUrl settings:setDic error:&recordError];
        
        self.recorder.delegate = self;
        
        //如果检测声波 必须要设置为YES
        self.recorder.meteringEnabled = YES;
        
        if (recordError) {
            NSLog(@"创建录音机对象时发生错误，错误信息:%@",error.localizedDescription);
            
            return nil;
        }
        
        [self.recorder prepareToRecord];
        
    }
    
    return _recorder;
}


- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag
{
    
    if (flag==YES) {
        
    }
    
}

- (void)setPlayUrl:(NSString *)playUrl
{
    _playUrl = playUrl;
}

- (void)dealloc
{
    
}












@end
